﻿using Devonline.Communication.Messages;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Devonline.Identity.Admin.Controllers;

[Route("api/[controller]")]
[ApiController]
[SecurityHeaders]
[Authorize(Roles = GROUP_MAINTAINERS)]
public class AccessRulesController(
    AuthorizationService authorizationService,
    ILogger<AccessRulesController> logger,
    IMessageCommunicator communicator,
    IDataService<AccessRule> dataService,
    IDataService<User> userService) :
    ODataModelServiceController<AccessRule, AccessRuleViewModel>(logger, dataService)
{
    private readonly IDataService<User> _userService = userService;
    private readonly AuthorizationService _authorizationService = authorizationService;
    private readonly IMessageCommunicator _communicator = communicator;

    [HttpPost]
    public override async Task<IActionResult> CreateAsync(AccessRuleViewModel viewModel)
    {
        switch (viewModel.IdentityType)
        {
            case IdentityType.All:
                viewModel.IdentityId = null;
                break;
            case IdentityType.Anonymous:
            case IdentityType.System:
                viewModel.IdentityId = _userService.GetQueryable(x => x.UserName == viewModel.IdentityType.ToString().ToLowerInvariant()).Select(x => x.Id).FirstOrDefault();
                break;
            default:
                if (string.IsNullOrWhiteSpace(viewModel.IdentityId))
                {
                    return BadRequest("必须选择一个授权对象!");
                }
                break;
        }

        await _dataService.AddAsync(viewModel);
        await RefreshUserInfoAsync(viewModel.IdentityType, viewModel.IdentityId);
        return Ok(viewModel);
    }
    [HttpPut]
    public override async Task<IActionResult> UpdateAsync(AccessRuleViewModel viewModel)
    {
        if (viewModel.IdentityType == IdentityType.All)
        {
            viewModel.IdentityId = null;
        }

        if (viewModel.IdentityType == IdentityType.Anonymous || viewModel.IdentityType == IdentityType.System)
        {
            viewModel.IdentityId = _userService.GetQueryable(x => x.UserName == viewModel.IdentityType.ToString().ToLowerInvariant()).Select(x => x.Id).FirstOrDefault();
        }

        await _dataService.UpdateAsync(viewModel);
        await RefreshUserInfoAsync(viewModel.IdentityType, viewModel.IdentityId);
        return Ok(viewModel);
    }
    [HttpDelete("{id}")]
    public override async Task<IActionResult> DeleteAsync(string id)
    {
        var entitySet = await _dataService.GetIfExistAsync(id);
        await _dataService.DeleteAsync(id);
        await RefreshUserInfoAsync(entitySet.IdentityType, entitySet.IdentityId);
        return Ok();
    }

    /// <summary>
    /// 此处的获取用户信息会自动刷新缓存
    /// </summary>
    /// <param name="userName"></param>
    /// <returns></returns>
    [HttpGet("GetUserInfo")]
    public async Task<IActionResult> GetUserInfoAsync(string userName)
    {
        _logger.LogDebug("user {user} get user info forced", HttpContext.GetUserName());
        var userContext = await _authorizationService.GetUserContextAsync(userName, true);
        if (userContext is null)
        {
            return NotFound();
        }

        return Ok(new UserInfo { User = userContext.User.Desensitize(), ResourceTree = userContext.ResourceTrees.Values });
    }
    [HttpGet("UserHasPermission/{userName}")]
    public async Task<IActionResult> UserHasPermissionAsync(string userName, string resource) => Ok(await _authorizationService.UserHasPermissionAsync(resource, userName));

    /// <summary>
    /// 刷新用户缓存
    /// </summary>
    /// <param name="identityType"></param>
    /// <param name="identityId"></param>
    /// <returns></returns>
    private async Task RefreshUserInfoAsync(IdentityType identityType, string? identityId)
    {
        var identityIds = new List<string>();
        if (!string.IsNullOrWhiteSpace(identityId))
        {
            identityIds.Add(identityId);
        }

        await _authorizationService.RefreshUserInfoAsync(_communicator, identityType, identityIds.ToArray());
    }
}